#ifndef SCENEMANAGER_H
#define SCENEMANAGER_H

#include <unordered_map>
#include <string>
#include <scene.h>
#include <thread>
#include <rlgl.h>

class SceneManager : public Scene{
private:
    std::unordered_map<std::string, Scene*> scenes;
    std::unordered_map<std::string, bool> initialized;
    std::string current;
    std::string target;
    std::thread* thread_init = nullptr;
    std::atomic<bool> thread_running{false};
public:
    SceneManager() = default;
    ~SceneManager(){
        for (auto& pair : scenes) {
            delete pair.second;
        }
        scenes.clear();
        current.clear();
    }

    void put(const std::string& name, Scene* scene){
        scenes.insert({name, scene});
        initialized.insert({name, false});
        if(current.empty()) switchTo(name);
    }

    Scene* get(std::string &name){
        if(scenes.find(name) != scenes.end()){
            return scenes[name];
        }else return nullptr;
    }

    void init() override {}

    void render(float dt) override{
        if(!current.empty())
            scenes[current]->render(dt);
    }

    bool switchTo(const std::string& name){
        
        if(scenes.find(name) != scenes.end()){
            target = name;

            if(!thread_running && thread_init != nullptr)
            {
                if (thread_init->joinable()) {
                    thread_init->join();
                    delete thread_init;
                    thread_init = nullptr;
                }
            }

            if(!initialized[target])
            {
                current = "loading";
                thread_running = true;
                if(name!="randmap")
                    thread_init = new std::thread([this](){
                        scenes[target]->init();
                        // std::this_thread::sleep_for(std::chrono::milliseconds(500));
                        initialized[target] = true;
                        current = target;
                        thread_running = false;
                    });
                else{
                    scenes[target]->init();
                    initialized[target] = true;
                    current = target;
                    thread_running = false;
                }
            }
            else current = name;
            
            return true;
        }else return false;
    }
};

#endif